home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / DELPHI32 / CALCULTR / MCALC / MCALC.PAS next >
Pascal/Delphi Source File  |  1996-07-24  |  76KB  |  1,914 lines

  1. (*                   MathCalc 32 Multithread Kernel (Object Pascal)
  2.                              (c) Daniel Doubrovkine
  3.    Stolen Technologies Inc. - University of Geneva - 1996 - All Rights Reserved
  4.                            for Scientific Calculator
  5.                    (part of the Expression Calculator 2.0)
  6.  
  7.    Disclaimer: There's no waranty of any kind for anything and the author will
  8.                not be help responsible for anything claimed, whatever cause or
  9.                gravity may be.
  10.  
  11.    my homepage is at www.infomaniak.ch/~dblock
  12.  
  13.    SOURCE IS NOT FREE!
  14.  
  15.    SOURCE MAY BE USED FOR FREE IN COMPLETE AND TOTAL FREEWARE SOFTWARE ONLY, OTHERWISE
  16.    PLEASE CONTACT ME FOR MORE DETAIL!
  17.  
  18.    ANY ILLEGAL USE OR SALE WILL BE PROSECUTED AT MAXIMUM EXTENT POSSIBLE UNDER THE
  19.    SWISS CRIMINAL LAW!
  20.  
  21.   last minute notes:
  22.        prime function were disabled since too much dependant from the task of the
  23.        calculator, you must maintain external references to general prime tables
  24.  
  25. *)
  26. unit MCalc;
  27.  
  28. interface
  29. uses Classes, TreeView, SysUtils, Dialogs, Math, WinProcs, Forms;
  30.  
  31. type
  32.   TCalcMode=(Deg,Rad,Hex,Bin,Oct);                                              {calculation modes currently supported}
  33.   TCalcThread = class (TThread)
  34.    protected
  35.      CalcString    : string;                                                    {initital string passed for calculation}
  36.      VarTree       : PNode;                                                     {variable tree passed, may be global!}
  37.      CalcTree      : PNode;                                                     {calculator tree will be used for expression analysis}
  38.      CalcMode      : TCalcMode;                                                 {calculation mode}
  39.      CharRead      : char;                                                      {last char analysed}
  40.      NextInteger   : integer;                                                   {next integer sign}
  41.      CalcPos       : integer;                                                   {current position in string for analysis}
  42.      NegativeParenthesis : boolean;                                             {internal purpose for string analysis, sign inversion for parenthesis}
  43.      ReadNode      : PNode;                                                     {current analysis tree node}
  44.      CalcNode      : PNode;                                                     {current calculation node}
  45.      NewSymbol     : integer;                                                   {currently analysed symbol (sin, cos...)}
  46.      CalcError     : Boolean;                                                   {was an error raised?}
  47.      RaisedError   : string;                                                    {the raised error string}
  48.      ErrorPosition : integer;                                                   {the raised error position}
  49.      CalcResult    : extended;                                                  {the extended result of the calculation}
  50.      CalcStrResult : string;                                                    {the string result of the calculation}
  51.      ShortStrResult: string;                                                    {the short string result of the calculation}
  52.      CalcId        : LongInt;                                                   {the id passed to the thread}
  53.      procedure     Execute; override;                                           {the execute thread routine, don't override if you don't understand}
  54.      procedure     UpdateNextInteger;                                           {update next integer sign}
  55.      procedure     ReadItem;                                                    {read the next item at analysis}
  56.      procedure     AnalyseExpression(Expression:PNOde);                         {analyse complete expression (recursive, but not reentrant at same thread}
  57.      function      Evaluation(Expression:PNode):extended;                       {evaluation of a correct mathematical tree}
  58.      (*procedure     PrimesAdd(PrimeToAdd: LongInt);*)                          {}
  59.      function      IntToHex(AnyLong: extended):string;                          {explicit conversions}
  60.      function      IntToBin(AnyLong: extended):string;
  61.      function      IntToOct(AnyLong: extended):string;
  62.    public                                                                       {creation of the calculation object}
  63.      constructor   Create(CalculateString:string;                               {the string to analyse and to calculate}
  64.                           MyVarTree:PNode;                                      {variable tree to use (uses TreeView)}
  65.                           ToCalcMode:TCalcMode;                                 {calculation mode}
  66.                           ThreadId:integer);                                    {thread id passed}
  67.      procedure     UpdateResult; virtual;                                       {update result procedure, does necessary stuff,
  68.                                                                                  you must override to get result or change code in unit directly}
  69.      end;
  70.  
  71. implementation
  72.  
  73.  
  74. (* RESULT CONVERSION *)
  75. function TCalcThread.IntToHex(AnyLong: extended):string;
  76.    function SecIntToHex(AnyLong:extended):string;
  77.       const
  78.       HexArray: string='0123456789ABCDEF';
  79.       begin
  80.       if AnyLong<16 then SecIntToHex:=HexArray[Trunc(AnyLong)+1] else
  81.       SecIntToHex:=SecIntToHex(Trunc(AnyLong/16))+SecIntToHex(AnyLong-Trunc(AnyLong/16)*16);
  82.       end;
  83.    var
  84.       IntToHexString: string;
  85.       Sign: integer;
  86.    begin
  87.         if AnyLong<0 then begin
  88.            Sign:=-1;
  89.            AnyLong:=-AnyLong;
  90.            end else Sign:=1;
  91.         IntToHexString:=SecIntToHex(AnyLong);
  92.         while Length(IntToHexString) mod 2>0 do IntToHexString:='0'+IntToHexString;
  93.         {IntToHex:=IntToHexString;}
  94.         if Sign=-1 then IntToHex:='-'+IntToHexString else IntToHex:=IntToHexString;
  95.    end;
  96.  
  97. function TCalcThread.IntToBin(AnyLong: extended):string;
  98.    function SecIntToBin(AnyLong: extended):string;
  99.       const
  100.       BinArray: string='01';
  101.       begin
  102.       if AnyLong<2 then SecIntToBin:=BinArray[Trunc(AnyLong)+1] else begin
  103.          SecIntToBin:=SecIntToBin(Trunc(AnyLong/2))+SecIntToBin(AnyLong-Trunc(AnyLong/2)*2);
  104.       end;
  105.       end;
  106.    var
  107.       IntToBinString: string;
  108.    begin
  109.         IntToBinString:=SecIntToBin(AnyLong);
  110.         while Length(IntToBinString) mod 4>0 do IntToBinString:='0'+IntToBinString;
  111.         IntToBin:=IntToBinString;
  112.    end;
  113.  
  114. function TCalcThread.IntToOct(AnyLong: extended):string;
  115.       const
  116.          OctArray: string='01234567';
  117.       var
  118.          Sign: integer;
  119.          SecIntToOct: string;
  120.       begin
  121.       if AnyLong<0 then begin
  122.          Sign:=-1;
  123.          AnyLong:=-AnyLong
  124.          end else Sign:=1;
  125.       if AnyLong<8 then SecIntToOct:=OctArray[Trunc(AnyLong)+1] else
  126.       SecIntToOct:=IntToOct(Trunc(AnyLong/8))+IntToOct(AnyLong-Trunc(AnyLong/8)*8);
  127.       if Sign=-1 then IntToOct:='-'+SecIntToOct else IntToOct:=SecIntToOct;
  128.       end;
  129.  
  130.  
  131. (* THREAD CONSTRUCTOR *)
  132. constructor TCalcThread.Create(CalculateString:string;MyVarTree:PNode;ToCalcMode:TCalcMode;ThreadId:integer);
  133. begin
  134.    CalcId:=ThreadId;
  135.    FreeOnTerminate:=True;
  136.    CalcString:=CalculateString;
  137.    VarTree:=MyVarTree;
  138.    CalcMode:=ToCalcMode;
  139.    NewSymbol:=0;
  140.    CalcError:=False;
  141.    CharRead:=' ';
  142.    ErrorPosition:=0;
  143.    NextInteger:=1;
  144.    inherited Create(False);
  145.    end;
  146.  
  147.    (*
  148. procedure TCalcThread.PrimesAdd(PrimeToAdd: LongInt);
  149. begin
  150.    {MessageDlg('Adding '+IntToStr(PrimeToAdd),mtInformation,[mbOk],0);}
  151.    Calculator.CurrentPrime:=PrimeToAdd;
  152.    ReAllocMem(Calculator.AllPrimes,(Calculator.PrimesCount+2)*SizeOf(LongInt));
  153.    Calculator.AllPrimes^[Calculator.PrimesCount]:=PrimeToAdd;
  154.    Calculator.AllPrimes^[Calculator.PrimesCount+1]:=0;
  155.    inc(Calculator.PrimesCount);
  156.    end;
  157.    *)
  158.  
  159. (* THREAD EXECUTOR *)
  160. procedure TCalcThread.Execute;
  161. begin
  162.    try
  163.    New(CalcTree,Create(NodeVariable,'Calculating Tree:'));
  164.    New(ReadNode,Create(NodeVariable,'?'));
  165.    if VarTree=nil then New(VarTree,Create(NodeVariable,'Variable occurences.'));
  166.    CalcNode:=CalcTree^.AddChild(NodeVariable,'Extended Calculator');
  167.    CalcNode:=CalcNode^.AddChild(NodeVariable,'(c) Daniel Doubrovkine');
  168.    CalcNode^.AddChild(NodeVariable,'University of Geneva - 1996');
  169.    CalcNode:=CalcNode^.AddChild(NodeValue,'0');
  170.    CalcPos:=1;
  171.    UpdateNextInteger;
  172.    if CalcError=true then begin
  173.       UpdateResult;
  174.       exit;
  175.       end;
  176.    ReadItem;
  177.    if CalcError=true then begin
  178.       UpdateResult;
  179.       exit;
  180.       end;
  181.    AnalyseExpression(CalcNode);
  182.    if CalcError=true then begin
  183.       UpdateResult;
  184.       exit;
  185.       end;
  186.    if (ReadNode.NodeType<>NodeOperator) or
  187.       (ReadNode.NodeContents.MyOperator <> '$') then begin
  188.       RaisedError:='missing operator';
  189.       CalcError:=true;
  190.       ErrorPosition:=CalcPos;
  191.       end;
  192.    if not CalcError then begin
  193.       CalcResult:=Evaluation(CalcNode);
  194.       if CalcError=False then begin
  195.          Str(CalcResult,CalcStrResult);
  196.          if (CalcStrResult='-0.0000000000') or
  197.             (CalcStrResult='0.00000000000') then begin
  198.             CalcResult:=0;
  199.             CalcStrResult:='0.00';
  200.             end;
  201.          end;
  202.        end;
  203.    UpdateResult;
  204.    exit;
  205.    except
  206.       CalcError:=True;
  207.       RaisedError:='abnormal exception, rerun the thread';
  208.       ErrorPosition:=0;
  209.       UpdateResult;
  210.       exit;
  211.       end;
  212.    end;
  213.  
  214.  
  215. (* THREAD RESULT UPDATER *)
  216. procedure TCalcThread.UpdateResult;
  217. var
  218.    i,j,k: integer;
  219. begin
  220.       if CalcError=False then begin
  221.          try
  222.             ShortStrResult:='';
  223.             if CalcMode=Bin then begin
  224.                if (CalcResult>=0) and (Trunc(CalcResult)=CalcResult) then
  225.                   ShortStrResult:=IntToBin(trunc(CalcResult))
  226.                   else begin
  227.                   ShortStrResult:='- E -';
  228.                   CalcStrResult:='non integer or negative result';
  229.                   end;
  230.                   end else
  231.                if CalcMode=Oct then begin
  232.                   if (Trunc(CalcResult)=CalcResult) then
  233.                   ShortStrResult:=IntToOct(trunc(CalcResult))
  234.                   else begin
  235.                   ShortStrResult:='- E -';
  236.                   CalcStrResult:='non integer result';
  237.                   end;
  238.                   end else
  239.                if CalcMode=Hex then begin
  240.                   if (Trunc(CalcResult)=CalcResult) then
  241.                   ShortStrResult:=IntToHex(trunc(CalcResult))
  242.                   else begin
  243.                   ShortStrResult:='- E -';
  244.                   CalcStrResult:='non integer result';
  245.                   end;
  246.                end else begin
  247.             CalcStrResult:=Trim(CalcStrResult);
  248.  
  249.             for i:=1 to Length(CalcStrResult) do if CalcStrResult[i]='E' then break;
  250.             if i<Length(CalcStrResult) then
  251.                CalcStrResult:=Trim(Copy(CalcStrResult,1,i-1)+'e'+Copy(CalcStrResult,i+1,Length(CalcStrResult)));
  252.             Str(CalcResult:0:2,ShortStrResult);
  253.             ShortStrResult:=Trim(ShortStrResult);
  254.             for i:=1 to Length(ShortStrResult) do if ShortStrResult[i]='E' then begin
  255.                ShortStrResult:=CalcStrResult;
  256.                break;
  257.                end;
  258.             end;
  259.           except
  260.           ShortStrResult:='N/A';
  261.           end;
  262.  
  263.        CalcStrResult:=Trim(CalcStrResult);
  264.        for i:=1 to Length(CalcStrResult) do if CalcStrResult[i]='E' then break;
  265.        if i<Length(CalcStrResult) then CalcStrResult:=Trim(Copy(CalcStrResult,1,i-1)+'e'+Copy(CalcStrResult,i+1,Length(CalcStrResult)));
  266.  
  267.        if ShortStrResult='-0.00' then begin
  268.           ShortStrResult:='0.00';
  269.           for i:=1 to Length(CalcStrResult) do if CalcStrResult[i]='e' then break;
  270.           j:=0;
  271.           if i<Length(CalcStrResult) then Val(Copy(CalcStrResult,i+1,Length(CalcStrResult)),j,k);
  272.           if j<-10 then CalcStrResult:='0.00000000000000e+0000';
  273.           CalcResult:=0;
  274.           end;
  275.       end;
  276.    end;
  277.  
  278. (* NEXT INTEGER SIGN *)
  279. procedure TCalcThread.UpdateNextInteger;
  280. begin
  281.    NextInteger:=0;
  282.    if CalcString[CalcPos]='-' then NextInteger:=-1;
  283.    if CalcString[CalcPos]='+' then NextInteger:=1;
  284.    if NextInteger<>0 then CalcPos:=CalcPos+1 else NextInteger:=1;
  285.    end;
  286.  
  287. (*GET NEXT ITEM FROM STRING*)
  288. procedure TCalcThread.ReadItem;
  289.    function CheckVariableTable(variable:string):PNode;
  290.    begin
  291.       CheckVariableTable:=VarTree^.FindItem(NodeVariable,variable);
  292.       end; {CheckVariableTable}
  293.    procedure ReadCh; {gets the next char}
  294.    begin
  295.       if CalcPos>Length(CalcString) then
  296.          CharRead := '$'
  297.       else begin
  298.          CharRead:=CalcString[CalcPos];
  299.          inc(CalcPos);
  300.          end; {else}
  301.       end; {ReadCh}
  302.    function ReadOctNumber:extended;
  303.    var
  304.       MyNumber:extended;
  305.    begin
  306.       try
  307.       MyNumber:=0;
  308.       while CharRead in ['0'..'7'] do begin
  309.             MyNumber := MyNumber * 8 + (ord(CharRead)-ord('0'));
  310.             ReadCh;
  311.             end;{while}
  312.       ReadOctNumber:=MyNumber*NextInteger;
  313.       except
  314.          CalcError:=true;
  315.          RaisedError := 'octal overflow';
  316.          ErrorPosition:= CalcPos;
  317.          ReadOctNumber:=0;
  318.          exit;
  319.       end;
  320.       end;
  321.    function ReadBinNumber:extended;
  322.    var
  323.       MyNumber:extended;
  324.    begin
  325.       try
  326.       MyNumber:=0;
  327.       while CharRead in ['0'..'1'] do begin
  328.         MyNumber := MyNumber * 2 + (ord(CharRead)-ord('0'));
  329.         ReadCh;
  330.       end;{while}
  331.       ReadBinNumber:=MyNumber*NextInteger;
  332.       except
  333.          CalcError:=true;
  334.          RaisedError := 'binary digit overflow';
  335.          ErrorPosition:= CalcPos;
  336.          ReadBinNumber:=0;
  337.          exit;
  338.       end;
  339.       end;
  340.    function ReadHexNumber:extended;
  341.    var
  342.       MyNumber:extended;
  343.    begin
  344.       try
  345.       MyNumber:=0;
  346.       while CharRead in ['0'..'9','A'..'F'] do begin
  347.          if CharRead in ['0'..'9'] then
  348.             MyNumber := MyNumber * 16 + (ord(CharRead)-ord('0'))
  349.             else
  350.             MyNumber := MyNumber * 16 + (ord(CharRead)-ord('A')+10);
  351.          ReadCh;
  352.       end;{while}
  353.       ReadHExNumber:=MyNumber*NextInteger;
  354.       except
  355.          CalcError:=true;
  356.          RaisedError := 'hexadecimal overflow';
  357.          ErrorPosition:= CalcPos;
  358.          ReadHexNumber:=0;
  359.          exit;
  360.       end;
  361.       end;{ReadNumber}
  362.    {check variable table for a variable, returns a pointer if node found}
  363.    function ReadNumber:extended;
  364.    var
  365.       MyNumber:extended;
  366.       dCounter:extended;
  367.    begin
  368.       try
  369.       MyNumber:=0;
  370.       while CharRead in ['0'..'9'] do begin
  371.          MyNumber := MyNumber * 10 + (ord(CharRead)-ord('0'));
  372.          ReadCh;
  373.       end;{while}
  374.       dCounter:=1;
  375.       if (CharRead='.') then begin
  376.          ReadCh;
  377.          while CharRead in ['0'..'9'] do begin
  378.             MyNumber:=MyNumber*10 + (ord(CharRead)-ord('0'));
  379.             DCounter:=DCounter*10;
  380.             ReadCh;
  381.             end;{while}
  382.          end;{if}
  383.       MyNumber:=MyNumber/DCounter;
  384.       if NextInteger<>0 then begin
  385.          MyNumber:=MyNumber*NextInteger;
  386.          NextInteger:=0;
  387.          end;{if}
  388.       ReadNumber:=MyNumber;
  389.       except
  390.          CalcError:=true;
  391.          RaisedError := 'decimal overflow';
  392.          ErrorPosition:= CalcPos;
  393.          ReadNumber:=0;
  394.          exit;
  395.       end;
  396.       end;{ReadNumber}
  397.    {check variable table for a variable, returns a pointer if node found}
  398.  
  399.  procedure ReadNotDecimal;
  400.    var {ReadItem}
  401.    SymbolProc:string;
  402.  begin
  403.    NegativeParenthesis:=False;
  404.    if CalcError=true then exit;
  405.    while CharRead=' ' do ReadCh;
  406.    with ReadNode^ do begin
  407.       case CharRead of
  408.          '0'..'9','A'..'F' : begin
  409.          {read an unsigned integer}
  410.                        NodeType:=NodeValue;
  411.                        if (CalcMode=hex) then NodeContents^.MyValue:=ReadHexNumber;
  412.                        if (CalcMode=bin) then NodeContents^.MyValue:=ReadBinNumber;
  413.                        if (CalcMode=oct) then NodeContents^.MyValue:=ReadOctNumber;
  414.                        end;{'0'..'9'}
  415.          'S','H','L','R','a'..'z' : begin
  416.                        SymbolProc:='';
  417.                               while CharRead in ['S','H','L','R','a'..'z'] do begin
  418.                                     SymbolProc:=SymbolProc+CharRead;
  419.                                     ReadCh;
  420.                                     end;{while}
  421.                                  if (CompareText(SymbolProc,'or')=0) or
  422.                                     (CompareText(SymbolProc,'and')=0) or
  423.                                     (CompareText(SymbolProc,'xor')=0) or
  424.                                     (CompareText(SymbolProc,'nor')=0) or
  425.                                     (CompareText(SymbolProc,'xnor')=0) or
  426.                                     (CompareText(SymbolProc,'nand')=0) then begin
  427.                                      CalcPos:=CalcPos-1;
  428.                                      NodeType:=NodeOperator;
  429.                                      NodeContents^.MyOperator:=SymbolProc;
  430.                                      ReadCh;
  431.                                  end else begin
  432.                                      NodeType:=NodeSingle;
  433.                                      NodeContents^.MySingle:=SymbolProc;
  434.                                      if NextInteger=-1 then NodeContents.MySingle:='-'+NodeContents.MySingle;
  435.                                      end;{else begin}
  436.  
  437.                                  end;{'A'..'z'}
  438.          '(': begin
  439.                  if NextInteger=-1 then NegativeParenthesis:=True;
  440.                  UpdateNextInteger;
  441.                  NodeType:=NodeOperator;
  442.                  NodeContents^.MyOperator:=CharRead;
  443.                  Readch;
  444.               end;
  445.          '+','-','*','/','^','%',',': begin
  446.                  UpdateNextInteger;
  447.                  NodeType:=NodeOperator;
  448.                  NodeContents^.MyOperator:=CharRead;
  449.                  ReadCh;
  450.                  end;
  451.          '!',')','$' : begin
  452.                  NodeType:=NodeOperator;
  453.                  NodeContents^.MyOperator:=CharRead;
  454.                  ReadCh;
  455.                  end;
  456.          else begin {else case}
  457.                  CalcError:=true;
  458.                  RaisedError := 'invalid character';
  459.                  ErrorPosition:= CalcPos;
  460.                  NodeType:=NodeOperator;
  461.                  NodeContents^.MyOperator:='$';
  462.                  end;{else}
  463.          end;{case}
  464.       end;{with}
  465.    end;
  466.  procedure ReadDegRad;
  467.    var {ReadItem}
  468.    SymbolProc:string;
  469.    TempVarString:string;
  470.    TempVarValue:extended;
  471.    TempNode:PNode;
  472.    TempStoreNode:PNode;
  473.    l:integer;
  474.  begin {ReadDegRad}
  475.    NegativeParenthesis:=False;
  476.    if CalcError=true then exit;
  477.    while CharRead=' ' do ReadCh;
  478.    with ReadNode^ do begin
  479.       case CharRead of
  480.          '.','0'..'9' : begin
  481.          {read an unsigned integer}
  482.                        NodeType:=NodeValue;
  483.                        NodeContents^.MyValue:=ReadNumber;
  484.                        end;{'0'..'9'}
  485.          'A'..'Z', 'a'..'z' : begin
  486.                                  SymbolProc:='';
  487.                                  while CharRead in ['A'..'Z','a'..'z'] do begin
  488.                                        SymbolProc:=SymbolProc+CharRead;
  489.                                        ReadCh;
  490.                                        end;{while}
  491.                                  if (CompareText(SymbolProc,'or')=0) or
  492.                                     (CompareText(SymbolProc,'and')=0) or
  493.                                     (CompareText(SymbolProc,'xor')=0) or
  494.                                     (CompareText(SymbolProc,'nor')=0) or
  495.                                     (CompareText(SymbolProc,'xnor')=0) or
  496.                                     (CompareText(SymbolProc,'nand')=0) or
  497.                                     (SymbolProc='\') or
  498.                                     (SymbolProc='m') or
  499.                                     (SymbolProc='e') then begin
  500.                                      CalcPos:=CalcPos-1;
  501.                                      UpdateNextInteger;
  502.                                      NodeType:=NodeOperator;
  503.                                      NodeContents^.MyOperator:=SymbolProc;
  504.                                      ReadCh;
  505.                                  end else
  506.                                  if (SymbolProc<>'E') and
  507.                                     (Length(SymbolProc)=1) then begin
  508.                                      NodeType:=NodeVariable;
  509.                                      NodeContents^.MyVariable := SymbolProc;
  510.                                      TempNode:=CheckVariableTable(SymbolProc[1]);
  511.                                      TempStoreNode:=TempNode;
  512.                                      if TempNode<>nil then
  513.                                      if NewSymbol>0 then begin
  514.                                         {TempNode.Remove;}
  515.                                         TempNode:=nil;
  516.                                         end;
  517.                                      if TempNode=nil then begin
  518.                                         TempNode:=VarTree^.AddChild(NodeVariable,SymbolProc[1]);
  519.                                         l:=1;
  520.                                         while (l<>0) do begin
  521.                                         if InputQuery('Variable prompt', 'Please enter a value for '+SymbolProc[1], TempVarString)=False then begin
  522.                                            CalcError:=True;
  523.                                            ErrorPosition:=CalcPos;
  524.                                            RaisedError:='cancelled at var assignment';
  525.                                            TempNode^.Remove;
  526.                                            exit;
  527.                                            end;
  528.                                         TempVarString:=Trim(TempVarString);
  529.                                         if CompareText(TempVarString,'pi')=0 then Str(Pi,TempVarString) else
  530.                                         if TempVarString='E' then Str(Exp(1.0),TempVarString);
  531.                                         Val(TempVarString,TempVarValue,l);
  532.                                         if TempVarValue=1 then;
  533.                                         end;
  534.                                         if TempStoreNode<>nil then TempStoreNode.Remove;
  535.                                         TempNode^.AddChild(NodeValue,Trim(TempVarString));
  536.                                        end;
  537.                                         NodeType:=NodeValue;
  538.                                         Val(CheckVariableTable(SymbolProc[1])^.Child(0)^.Contents,TempVarValue,l);
  539.                                         NodeContents^.MyValue:=NextInteger*TempVarValue;
  540.                                      end{<>'E'}
  541.                                  else begin
  542.                                          if CompareText(SymbolProc,'pi')=0 then begin
  543.                                              NodeType:=NodeValue;
  544.                                              NodeContents^.MyValue:=NextInteger*Pi;
  545.                                              end{if}
  546.                                          else
  547.                                              if SymbolProc='E' then begin
  548.                                                 NodeType:=NodeValue;
  549.                                                 NodeContents^.MyValue:=NextInteger*Exp(1.0);
  550.                                                 end{='E'}
  551.                                              else begin
  552.                                                 if (CompareText(SymbolProc,'new')=0) then inc(NewSymbol);
  553.                                                 NodeType:=NodeSingle;
  554.                                                 NodeContents^.MySingle:=SymbolProc;
  555.                                                 if NextInteger=-1 then NodeContents.MySingle:='-'+NodeContents.MySingle;
  556.                                              end;
  557.                                          end;{else begin}
  558.                                  end;{'A'..'z'}
  559.          '(': begin
  560.                  if NextInteger=-1 then NegativeParenthesis:=True;
  561.                  UpdateNextInteger;
  562.                  NodeType:=NodeOperator;
  563.                  NodeContents^.MyOperator:=CharRead;
  564.                  Readch;
  565.               end;
  566.          '+','-','*','/','^','ª','%','\': begin
  567.                  UpdateNextInteger;
  568.                  NodeType:=NodeOperator;
  569.                  NodeContents^.MyOperator:=CharRead;
  570.                  ReadCh;
  571.                  end;
  572.          ',': begin
  573.                  UpdateNextInteger;
  574.                  NodeType:=NodeOperator;
  575.                  NodeContents^.MyOperator:=CharRead;
  576.                  ReadCh;
  577.               end;
  578.          '!',')','$' : begin
  579.                  NodeType:=NodeOperator;
  580.                  NodeContents^.MyOperator:=CharRead;
  581.                  ReadCh;
  582.                  end;
  583.          else begin {else case}
  584.                   CalcError:=true;
  585.                   RaisedError := 'invalid character';
  586.                   ErrorPosition:= CalcPos;
  587.                  NodeType:=NodeOperator;
  588.                  NodeContents^.MyOperator:='$';
  589.                  end;{else}
  590.          end;{case}
  591.       end;{with}
  592.       end;
  593.    begin {ReadItem}
  594.       if (CalcMode<>Deg) and (CalcMode<>Rad) then ReadNotDecimal else ReadDegRad;
  595.    end;{ReadItem}
  596.  
  597.  
  598. (* TRIANGULAR EXPRESSION ANALYSIS, THE VERY BEST WAY TO ANALYSE AN EXPRESSION WITH
  599.    PRIORITIES *)
  600. procedure TCalcThread.AnalyseExpression(Expression:PNode);
  601.   procedure Term(Expression:PNode);
  602.    procedure Percentage(Expression:PNode);
  603.     procedure AnyRoot(Expression:PNode);
  604.      procedure Power(Expression:PNode);
  605.       procedure TenPower(Expression:PNode);
  606.        procedure Factor(Expression:PNode);
  607.         procedure Operator(Expression:PNode);
  608.          function ct(MyCompareText:string):boolean;
  609.          begin
  610.            if (CompareText(Expression^.Contents,MyCompareText)=0)
  611.            or (CompareText(Expression^.Contents,'-'+MyCompareText)=0) then ct:=true else ct:=false;
  612.            end;
  613.           var
  614.              NegativeLocalParenthesis:boolean;
  615.              ParamCount:integer;
  616.              ParamRead: integer;
  617.           begin
  618.              NegativeLocalParenthesis:=False;
  619.              if (ReadNode^.NodeType=NodeSingle) then begin
  620.                  ParamCount:=0;
  621.                  Expression^.NodeType:=NodeSingle;
  622.                  Expression^.NodeContents^.MySingle:=ReadNode^.NodeContents^.MySingle;
  623.  
  624.                  if ct('binom') then ParamCount:=1 else
  625.                  if ct('logn') then ParamCount:=1 else
  626.                  if ct('max') then ParamCount:=-1 else
  627.                  if ct('min') then ParamCount:=-1 else
  628.                  if ct('shr') then ParamCount:=1 else
  629.                  if ct('shl') then ParamCount:=1 else
  630.                  if ct('gcd') then ParamCount:=-1 else
  631.                  if ct('pgcd') then ParamCount:=-1 else
  632.                  if ct('gamma') then ParamCount:=1 else
  633.                  if ct('beta') then ParamCount:=2 else
  634.                  if ct('lcm') then ParamCount:=-1 else
  635.                  if ct('ppcm') then ParamCount:=-1 else
  636.                  if ct('average') then ParamCount:=-1;
  637.  
  638.                  if not(ct('new')) and (NewSymbol>0) then inc(NewSymbol);
  639.                  ReadItem;
  640.                  if CalcError=true then exit;
  641.  
  642.                if (ReadNode^.NodeType<>NodeOperator) or
  643.                   (ReadNode^.NodeContents^.MyOperator<>'(') then begin
  644.                      CalcError:=True;
  645.                      RaisedError:='function requires "("';
  646.                      ErrorPosition:=CalcPos;
  647.                      exit;
  648.                    end;
  649.  
  650.                    ReadItem;
  651.                    if CalcError=true then exit;
  652.                    AnalyseExpression(Expression^.AddChild(NodeValue,'0'));
  653.  
  654.                ParamRead:=1;
  655.                if ParamCount<0 then begin
  656.                   while (ReadNode^.NodeType=NodeOperator) and
  657.                         (ReadNode^.NodeContents^.MyOperator=',') {and
  658.                         (ParamRead<255)} do begin
  659.                          ReadItem;
  660.                          inc(ParamRead);
  661.                          AnalyseExpression(Expression^.Addchild(NodeValue,'0'));
  662.                          if CalcError=true then exit;
  663.                          end;
  664.                   if abs(ParamRead)<abs(ParamCount) then begin
  665.                      CalcError:=True;
  666.                      RaisedError:='insuf. params for '+Expression^.Contents;
  667.                      ErrorPosition:=CalcPos;
  668.                      exit;
  669.                      end;
  670.                   end;
  671.  
  672.                while ParamCount>0 do begin
  673.                  if (ReadNode^.NodeType<>NodeOperator) or
  674.                     (ReadNode^.NodeContents^.MyOperator<>',') then begin
  675.                      CalcError:=True;
  676.                      RaisedError:='insuf. params for '+Expression^.Contents;
  677.                      ErrorPosition:=CalcPos;
  678.                      exit;
  679.                      end;
  680.                  ReadItem;
  681.                  AnalyseExpression(Expression^.Addchild(NodeValue,'0'));
  682.                  ParamCount:=ParamCount-1;
  683.                  if CalcError=true then exit;
  684.                end;
  685.  
  686.                if (ReadNode^.NodeType<>NodeOperator) or
  687.                   (ReadNode^.NodeContents^.MyOperator<>')') then begin
  688.                      CalcError:=True;
  689.                      RaisedError:='")" expected';
  690.                      ErrorPosition:=CalcPos;
  691.                      exit;
  692.                    end;{')'}
  693.                 if NewSymbol>0 then NewSymbol:=NewSymbol-1;
  694.                 ReadItem;
  695.                 if CalcError=true then exit;
  696.                 end {NodeSingle} else
  697.             if (ReadNode^.NodeType=NodeValue) then begin
  698.                 Expression^.NodeType:=NodeValue;
  699.                 Expression^.NodeContents^.MyValue:=ReadNode^.NodeContents^.MyValue;
  700.                 ReadItem;
  701.                 if CalcError=true then exit;
  702.                 end{NodeValue} else
  703.             if (ReadNode^.NodeType=NodeVariable) then begin
  704.                 Expression^.NodeType:=NodeVariable;
  705.                 Expression^.NodeContents^.MyVariable:=ReadNode^.NodeContents^.MyVariable;
  706.                 ReadItem;
  707.                 if CalcError=true then exit;
  708.                 end {variable} else
  709.             if (ReadNode^.NodeType=NodeOperator) and
  710.                (ReadNode^.NodeContents^.MyOperator='(') then begin
  711.  
  712.                if NegativeParenthesis then begin
  713.                 NegativeLocalParenthesis:=True;
  714.                 if Expression^.Parent^.Child(1)=nil then begin
  715.                    Expression^.Parent^.Child(0)^.NodeType:=NodeOperator;
  716.                    Expression^.Parent^.Child(0)^.NodeContents^.MyOperator:='-';
  717.                    Expression:=Expression^.Parent^.Child(0);
  718.                    end else begin
  719.                    Expression^.Parent^.Child(1)^.NodeType:=NodeOperator;
  720.                    Expression^.Parent^.Child(1)^.NodeContents^.MyOperator:='-';
  721.                    Expression:=Expression^.Parent^.Child(1);
  722.                    end;
  723.                   Expression^.AddChild(NodeValue,'0');
  724.                   Expression:=Expression^.AddChild(NodeValue,'0');
  725.                   end;
  726.                 NegativeParenthesis:=False;
  727.                 ReadItem;
  728.  
  729.                 if CalcError=true then exit;
  730.                 if Expression^.Parent^.Child(1)=nil then
  731.                 AnalyseExpression(Expression^.Parent^.Child(0)) else
  732.                 AnalyseExpression(Expression^.Parent^.Child(1));
  733.                 if NegativeLocalParenthesis then Expression:=Expression^.Parent;
  734.                 if (ReadNode^.NodeType<>NodeOperator) or
  735.                    (ReadNode^.NodeContents^.MyOperator<>')') then begin
  736.                      CalcError:=True;
  737.                      RaisedError:='")" expected';
  738.                      ErrorPosition:=CalcPos;
  739.                      exit;
  740.                     end;{')'}
  741.                 ReadItem;
  742.                 if CalcError=true then exit;
  743.                 end {'('}
  744.             else begin
  745.                      CalcError:=True;
  746.                      RaisedError:='unexpected sign, val, var or funct';
  747.                      ErrorPosition:=CalcPos;
  748.                      exit;
  749.                  end; {else}
  750.             end;{Operator}
  751.         begin {Factor}
  752.            Operator(Expression);
  753.            if CalcError=true then exit;
  754.            while (ReadNode^.NodeType=NodeOperator) and
  755.                  (ReadNode^.NodeContents^.MyOperator='!') do begin
  756.                   Expression:=Expression^.InsertLevel(ReadNode);
  757.                   ReadNode^.NodeType:=NodeValue;
  758.                   ReadNode^.NodeContents^.MyValue:=1;
  759.                   Operator(Expression^.Parent^.Child(1));
  760.                   if CalcError=true then exit;
  761.                   Expression:=Expression^.Parent;
  762.                   end;{while}
  763.            end; {Factor}
  764.       begin {TenPower}
  765.          Factor(Expression);
  766.          if CalcError=true then exit;
  767.          while (ReadNode^.NodeType=NodeOperator) and
  768.                (ReadNode^.NodeContents^.MyOperator='e') do begin
  769.                 ReadNode^.NodeContents^.MyOperator:='*';
  770.                 Expression:=Expression^.InsertLevel(ReadNode);
  771.                 Expression^.NodeType:=NodeOperator;
  772.                 Expression^.NodeContents^.MyOperator:='^';
  773.                 Expression^.AddChild(NodeValue,'10');
  774.                 Expression:=Expression^.AddChild(NodeValue,'0');
  775.                 ReadNode^.NodeType:=NodeValue;
  776.                 ReadNode^.NodeContents^.MyValue:=0;
  777.                 ReadItem;
  778.                 Factor(Expression^.Parent^.Child(1));
  779.                 if CalcError=true then exit;
  780.                 Expression:=Expression^.Parent;
  781.                 end;{while}
  782.         end;{TenPower}
  783.       begin {Power}
  784.          TenPower(Expression);
  785.          if CalcError=true then exit;
  786.          while (ReadNode^.NodeType=NodeOperator) and
  787.                (ReadNode^.NodeContents^.MyOperator='^') do begin
  788.                 Expression:=Expression^.InsertLevel(ReadNode);
  789.                 ReadItem;
  790.                 TenPower(Expression^.Parent^.Child(1));
  791.                 if CalcError=true then exit;
  792.                 Expression:=Expression^.Parent;
  793.                 end;{while}
  794.          end;{Power}
  795.       begin{AnyRoot}
  796.          Power(Expression);
  797.          if CalcError=true then exit;
  798.          while(ReadNode^.NodeType=NodeOperator) and
  799.               (ReadNode^.NodeContents^.MyOperator='\') do begin
  800.               Expression:=Expression^.InsertLevel(ReadNode);
  801.               ReadItem;
  802.               Power(Expression^.Parent^.Child(1));
  803.               if CalcError=true then exit;
  804.               Expression:=Expression^.Parent;
  805.               end;
  806.          end;{AnyRoot}
  807.    begin {Percentage}
  808.         AnyRoot(Expression);
  809.         if CalcError=true then exit;
  810.         while (ReadNode^.NodeType=NodeOperator) and
  811.               (ReadNode^.NodeContents^.MyOperator='%') do begin
  812.                Expression:=Expression^.InsertLevel(ReadNode);
  813.                ReadItem;
  814.                AnyRoot(Expression^.Parent^.Child(1));
  815.                if CalcError=true then exit;
  816.                Expression:=Expression^.Parent;
  817.                end;{while}
  818.         end;{Percentage}
  819.    begin {Term}
  820.       Percentage(Expression);
  821.       if CalcError=true then exit;
  822.       while (ReadNode^.NodeType=NodeOperator) and
  823.             ((CompareText(ReadNode^.NodeContents^.MyOperator,'xor')=0) or
  824.              (CompareText(ReadNode^.NodeContents^.MyOperator,'or')=0) or
  825.              (CompareText(ReadNode^.NodeContents^.MyOperator,'and')=0) or
  826.              (CompareText(ReadNode^.NodeContents^.MyOperator,'nor')=0) or
  827.              (CompareText(ReadNode^.NodeContents^.MyOperator,'xnor')=0) or
  828.              (CompareText(ReadNode^.NodeContents^.MyOperator,'nand')=0) or
  829.  
  830.              (ReadNode^.NodeContents^.MyOperator='z') or {xnor}
  831.              (ReadNode^.NodeContents^.MyOperator='n') or {nor}
  832.              (ReadNode^.NodeContents^.MyOperator='d') or {nand}
  833.              (ReadNode^.NodeContents^.MyOperator='x') or {xor}
  834.              (ReadNode^.NodeContents^.MyOperator='o') or {or}
  835.              (ReadNode^.NodeContents^.MyOperator='a') or {and}
  836.  
  837.              (ReadNode^.NodeContents^.MyOperator='*') or
  838.              (ReadNode^.NodeContents^.MyOperator='/') or
  839.              (ReadNode^.NodeContents^.MyOperator='m') or
  840.              (ReadNode^.NodeContents^.MyOperator='ª')) do begin
  841.               Expression:=Expression^.InsertLevel(ReadNode);
  842.               ReadItem;
  843.               Percentage(Expression^.Parent^.Child(1));
  844.               if CalcError=true then exit;
  845.               Expression:=Expression^.Parent;
  846.               end;{while}
  847.       end; {Term}
  848.   begin {Expression}
  849.      Term(Expression);
  850.      if CalcError=true then exit;
  851.      while (ReadNode^.NodeType=NodeOperator) and
  852.            ((ReadNode^.NodeContents^.MyOperator='+') or
  853.             (ReadNode^.NodeContents^.MyOperator='-')) do begin
  854.              Expression:=Expression^.InsertLevel(ReadNode);
  855.              ReadItem;
  856.              Term(Expression^.Parent^.Child(1));
  857.              if CalcError=true then exit;
  858.              Expression:=Expression^.Parent;
  859.              end;{while}
  860.      end; {Expression}
  861.  
  862. (* MATHEMATICAL EVALUATION OF THE CONSTRUCTED TREE *)
  863. function TCalcThread.Evaluation(Expression:PNode):extended;
  864.    type
  865.       MArray=array[0..7] of LongInt;
  866.       PArray=array[0..4] of LongInt;
  867.    const
  868.       MersiennePArray:MArray=(2,3,5,7,13,17,19,31);
  869.       MersienneArray:MArray=(3,7,31,127,8191,131071,524287,2147483647);
  870.       PerfectArray:PArray=(6,28,496,8128,33550336);
  871.  
  872. {------- returns the closest inferiour perfect number ----------}
  873. function Perfect(n:extended): extended;
  874. var
  875.       i:integer;
  876.    begin
  877.       if (n<6) or (n>Power(2,32)) then begin
  878.          RaisedError:='invalid perfect bounds';
  879.          CalcError:=true;
  880.          ErrorPosition:=0;
  881.          Perfect:=0;
  882.          exit;
  883.          end;
  884.       for i:=4 downto 0 do begin
  885.           if n>=PerfectArray[i] then begin
  886.              Perfect:=PerfectArray[i];
  887.              exit;
  888.              end;
  889.          end;
  890.          Perfect:=6;
  891.       end;
  892.    {------- returns the generator for a mersienne number ----------}
  893.    function MersienneP(n: extended): extended;
  894.    var
  895.       i:integer;
  896.    begin
  897.       for i:=0 to 7 do begin
  898.           if n=MersienneArray[i] then begin
  899.              MersienneP:=MersiennePArray[i];
  900.              exit;
  901.              end;
  902.          end;
  903.          RaisedError:='not a mersienne prime';
  904.          CalcError:=true;
  905.          ErrorPosition:=0;
  906.          MersienneP:=0;
  907.       end;
  908.    {-------- returns a mersienne number for a mersienne generator -----------}
  909.    function PMersienne(n: extended): extended;
  910.    var
  911.       i:integer;
  912.    begin
  913.       for i:=0 to 7 do begin
  914.           if n=MersiennePArray[i] then begin
  915.              PMersienne:=MersienneArray[i];
  916.              exit;
  917.              end;
  918.          end;
  919.          RaisedError:='not a mersienne generator';
  920.          CalcError:=true;
  921.          ErrorPosition:=0;
  922.          PMersienne:=0;
  923.       end;
  924.    {------- returns the closest inferiour mersienne number known ---------------}
  925.    function MersienneN(n: extended): extended;
  926.    var
  927.       i:integer;
  928.    begin
  929.       if (n<3) or (n>Power(2,32)) then begin
  930.          RaisedError:='invalid mersienne bounds';
  931.          CalcError:=true;
  932.          ErrorPosition:=0;
  933.          MersienneN:=0;
  934.          exit;
  935.          end;
  936.       for i:=7 downto 0 do begin
  937.           if n>=MersienneArray[i] then begin
  938.              MersienneN:=MersienneArray[i];
  939.              exit;
  940.              end;
  941.          end;
  942.          MersienneN:=3;
  943.       end;
  944.    {----------- returns the closest inferiour mersienne generator known ----------------}
  945.    function MersienneG(n: extended): extended;
  946.    var
  947.       i:integer;
  948.    begin
  949.       if (n<2) or (n>32) then begin
  950.          RaisedError:='invalid mersienne gen bounds';
  951.          CalcError:=true;
  952.          ErrorPosition:=0;
  953.          MersienneG:=0;
  954.          exit;
  955.          end;
  956.       for i:=7 downto 0 do begin
  957.           if n>=MersiennePArray[i] then begin
  958.              MersienneG:=MersiennePArray[i];
  959.              exit;
  960.              end;
  961.          end;
  962.          MersienneG:=3;
  963.       end;
  964.    {- prime numbers ------- awesome multitasking routine threaded to the same table}
  965.  
  966. (*
  967. function MyPrime(n:extended):extended;
  968.  procedure CalculateTPrime;
  969.     var
  970.       CurrentPrime: LongInt;
  971.       CurrentCounter:LongInt;
  972.       prime:boolean;
  973.       number,max_div,divisor:longint;
  974.       NextWillTerminate:boolean;
  975.       LastShownPrime: LongInt;
  976.     begin
  977.       Calculator.PrimeTableUser:=Handle;
  978.       Calculator.PrimeTableInUse:=True;
  979.       NextWillTerminate:=False;
  980.       CurrentPrime:=Calculator.AllPrimes^[Calculator.PrimesCount-1]+2;
  981.       LastShownPrime:=CurrentPrime;
  982.       Calculator.CalcGrid.Cells[1,GridId]:='Current prime: '+IntToStr(CurrentPrime);
  983.       for number:=Calculator.CurrentPrime to MaxInt do begin
  984.          CurrentCounter:=2;
  985.          max_div:=round(Sqrt(number)+0.5);
  986.          divisor:=Calculator.AllPrimes^[CurrentCounter];
  987.          prime:=number mod divisor <> 0;
  988.          while prime and (divisor<=max_div) do begin
  989.              prime:=number mod divisor <> 0;
  990.              inc(CurrentCounter);
  991.              divisor:=Calculator.AllPrimes[CurrentCounter];
  992.              end;
  993.         if prime then begin
  994.  
  995.         CurrentPrime:=number;
  996.  
  997.         if Calculator.AllPrimes^[Calculator.PrimesCount-1]<CurrentPrime then
  998.            PrimesAdd(CurrentPrime);
  999.  
  1000.         if (CurrentPrime-LastShownPrime>20000) then begin
  1001.            Calculator.CalcGrid.Cells[1,GridId]:='Current prime: '+IntToStr(CurrentPrime);
  1002.            LastShownPrime:=CurrentPrime;
  1003.            end;
  1004.         if NextWillTerminate=true then begin
  1005.            Calculator.PrimeTableInUse:=False;
  1006.            exit;
  1007.            end;
  1008.  
  1009.         if number>n then NextWillTerminate:=True;
  1010.         end;
  1011.  
  1012.         end;
  1013.  
  1014.       end;
  1015.  
  1016. var
  1017.    sign: integer;
  1018.    i : longint;
  1019.    begin
  1020.       if (n>-1) and (n<1) then begin
  1021.          RaisedError:='Prime requires values |x|>1';
  1022.          CalcError:=true;
  1023.          ErrorPosition:=0;
  1024.          MyPrime:=0;
  1025.          exit;
  1026.          end;
  1027.       if n>maxint then begin
  1028.          RaisedError:='prime limit too large';
  1029.          CalcError:=true;
  1030.          ErrorPosition:=0;
  1031.          MyPrime:=0;
  1032.          exit;
  1033.          end;
  1034.       if n<0 then sign:=-1 else sign:=1;
  1035.       n:=abs(n);
  1036.       while Calculator.PrimeTableInUse do begin
  1037.             Sleep(0);
  1038.             if n<=Calculator.CurrentPrime then break;
  1039.             end;
  1040.       if (n>Calculator.CurrentPrime) then CalculateTPrime;
  1041.       for i:=Calculator.PrimesCount-1 downto 0 do begin
  1042.        if n>=Calculator.AllPrimes^[i] then begin
  1043.           MyPrime:=Calculator.AllPrimes^[i]*Sign;
  1044.           exit;
  1045.           end;
  1046.       end;
  1047.       MyPrime:=0;
  1048.       RaisedError:='severe O.S. bug, please retry';
  1049.       ErrorPosition:=0;
  1050.       CalcError:=True;
  1051.    end;
  1052. *)
  1053. {- Fibonacci -}
  1054.    function Fib(n:extended):extended;
  1055.    var
  1056.    {FibArray:array[0..2] of extended;}
  1057.     FA1, FA2, FA3 : extended;
  1058.    begin
  1059.       if n<2 then Fib:=n else
  1060.       if n=2 then Fib:=1 else begin
  1061.          FA2:=1;
  1062.          FA3:=2;
  1063.          while n>3 do begin
  1064.             FA1:=FA2;
  1065.             FA2:=FA3;
  1066.             FA3:=FA1+FA3;
  1067.             n:=n-1;
  1068.             end;
  1069.             Fib:=FA3;
  1070.             end;
  1071.          end;
  1072. {- PGCD -}
  1073.    function PGCD(u,v:extended):extended;
  1074.    var
  1075.        t: extended;
  1076.    begin
  1077.       if (trunc(u)<>u) or (trunc(v)<>v) then begin
  1078.          RaisedError:='GCD requires integers';
  1079.          CalcError:=true;
  1080.          ErrorPosition:=0;
  1081.          PGCD:=0;
  1082.          exit;
  1083.          end;
  1084.       while (v<>0) do begin
  1085.          t:=u - (trunc(u / v))*v;
  1086.          u:=v;
  1087.          v:=t;
  1088.          end;
  1089.       PGCD:=abs(u);
  1090.      end;
  1091.  
  1092. function gcd(g:extended):extended;
  1093. var
  1094.    ChildValue: extended;
  1095.    i:integer;
  1096. begin
  1097.    i:=1;
  1098.    while (Expression^.Child(i)<>nil) do begin
  1099.          ChildValue:=Evaluation(Expression^.Child(i));
  1100.          g:=PGCD(ChildValue,g);
  1101.          inc(i);
  1102.          end;
  1103.    gcd:=g;
  1104.    end;
  1105.  
  1106. {-- least common multiple ---------------------------------------------------------}
  1107. function lcm(g:extended):extended;
  1108. var
  1109.    ChildValue: extended;
  1110.    i:integer;
  1111. begin
  1112.    i:=1;
  1113.    while (Expression^.Child(i)<>nil) do begin
  1114.          ChildValue:=Evaluation(Expression^.Child(i));
  1115.  
  1116.       if (trunc(ChildValue)<>ChildValue) or (trunc(g)<>g) then begin
  1117.          RaisedError:='LCM requires integers';
  1118.          CalcError:=true;
  1119.          ErrorPosition:=0;
  1120.          lcm:=0;
  1121.          exit;
  1122.          end;
  1123.  
  1124.          g:=abs(trunc(g/pgcd(g,ChildValue))*ChildValue);
  1125.          inc(i);
  1126.          end;
  1127.    lcm:=g;
  1128.    end;
  1129. {- VariableValue ---------------------------------------------------------------------}
  1130.    function VariableValue(Variable:string):extended;
  1131.    begin
  1132.          if VarTree^.FindItem(NodeVariable,Variable)=nil then
  1133.          VariableValue:=VarTree^.FindItem(NodeVariable,'-'+Variable)^.Child(0)^.NodeContents^.MyValue
  1134.          else
  1135.          VariableValue:=VarTree^.FindItem(NodeVariable,Variable)^.Child(0)^.NodeContents^.MyValue;
  1136.       end;{VariableValue}
  1137. {- Gamma -----------------------------------------------------------------------------}
  1138. function ShortGamma(Alpha:extended;Step:extended;Infinity:longint):extended;
  1139.   function GIntegral(x:extended):extended;
  1140.       begin
  1141.       GIntegral:=Power(x,Alpha-1)/Power(Exp(1),x);
  1142.       end;
  1143.      var i:extended;
  1144.          TempGamma:extended;
  1145.        begin
  1146.        if (Step>=1) or (Step=0) then begin
  1147.           CalcError:=True;
  1148.           ErrorPosition:=0;
  1149.           RaisedError:='inaccurate (>=1 ªª =0) step for gamma';
  1150.           ShortGamma:=0;
  1151.           exit;
  1152.           end;
  1153.        i:=0;
  1154.        TempGamma:=0;
  1155.        while i<Infinity do begin
  1156.         i:=i+Step;
  1157.         TempGamma:=TempGamma+GIntegral(i)*Step;
  1158.        end;
  1159.        ShortGamma:=TempGamma;
  1160.        end;
  1161. {- Factor ----------------------------------------------------------------------------}
  1162.    function Factor(n,step:extended):extended;
  1163.      var i:integer;
  1164.          NewGamma:extended;
  1165.      begin
  1166.      if (n<0) then
  1167.        if (trunc(n)=n) then begin
  1168.           Factor:=0;
  1169.           RaisedError:='factor results to infinite value';
  1170.           CalcError:=true;
  1171.           ErrorPosition:=0;
  1172.           exit;
  1173.         end else begin
  1174.             NewGamma:=ShortGamma(abs(1+frac(n))+1,step,50+abs(trunc(n*1.2)));
  1175.             for i:=-1 to trunc(abs(n))-1 do begin
  1176.                 NewGamma:=NewGamma/(frac(n)-i);
  1177.                 end;
  1178.             Factor:=NewGamma;
  1179.         end else
  1180.      if n=0 then Factor:=1 else
  1181.      if n=1 then Factor:=1 else
  1182.      if n=2 then Factor:=2 else
  1183.      if n=3 then Factor:=6 else
  1184.      Factor:=ShortGamma(n+1,step,50+trunc(n*1.2));
  1185.     end;
  1186. function Gamma(Alpha:extended;Step:extended):extended;
  1187. begin
  1188.    Gamma:=Factor(Alpha-1,Step);
  1189.    end;
  1190. function Beta(a,b,Step: extended): extended;
  1191. begin
  1192.    Beta:=Gamma(a,step)*Gamma(b,step)/Gamma(a+b,step);
  1193.    end;
  1194. {-------------------------------------------------------------------------------------}
  1195. function Precise(Value:extended;DecimalPrecision:integer):extended;
  1196. var NewValue:extended;
  1197. begin
  1198.    try
  1199.      NewValue:=Value*(Power(10,DecimalPrecision));
  1200.      NewValue:=Trunc(NewValue);
  1201.      NewValue:=NewValue/(Power(10,DecimalPrecision));
  1202.      Precise:=NewValue;
  1203.      except
  1204.      Precise:=Value;
  1205.      end;
  1206.    end;
  1207. {- Coth -------------------------------------------------------------------------------}
  1208. function Coth(g:extended):extended;
  1209. begin
  1210.    if exp(g)=exp(-g) then begin
  1211.       RaisedError:='division by zero at Coth()';
  1212.       CalcError:=true;
  1213.       ErrorPosition:=0;
  1214.       Coth:=0;
  1215.       exit;
  1216.       end;
  1217.    Coth:=(exp(g)+exp(-g))/(exp(g)-exp(-g));
  1218.    end;
  1219. {- MyRandom ---------------------------------------------------------------------------}
  1220. function MyRandom(g:extended):extended;
  1221. begin
  1222.    Randomize;
  1223.    if g<=0 then begin
  1224.       RaisedError:='senseless random request';
  1225.       CalcError:=true;
  1226.       ErrorPosition:=0;
  1227.       MyRandom:=0;
  1228.       exit;
  1229.       end;
  1230.    MyRandom:= Random(trunc(g));
  1231.    end;
  1232. {- Sec -------------------------------------------------------------------------}
  1233. function Sec(g:extended):extended;
  1234. begin
  1235.    if CalcMode=deg then g:=DegToRad(g);
  1236.    if Precise(Cos(g),10)=0 then begin
  1237.       Sec:=0;
  1238.       RaisedError:='division by zero at Sec()';
  1239.       CalcError:=true;
  1240.       ErrorPosition:=0;
  1241.       exit;
  1242.       end;
  1243.    Sec:= 1/Precise(cos(g),10);
  1244.    end;
  1245. {- MySqrt ----------------------------------------------------------------------}
  1246. function MySqrt(g:extended):extended;
  1247. begin
  1248.    if g<0 then begin
  1249.       MySqrt:=0;
  1250.       RaisedError:='sqrt of a negative value';
  1251.       CalcError:=true;
  1252.       ErrorPosition:=0;
  1253.       exit;
  1254.       end;
  1255.    MySqrt:= sqrt(g)
  1256.    end;
  1257. {- MySin ------------------------------------------------------------------------}
  1258. function MySin(g:extended):extended;
  1259. begin
  1260.    if CalcMode=deg then g:=DegToRad(g);
  1261.    MySin:=Precise(Sin(g),10);
  1262.    end;
  1263. {- MyCos ------------------------------------------------------------------------}
  1264. function MyCos(g:extended):extended;
  1265. begin
  1266.    if CalcMode=deg then g:=DegToRad(g);
  1267.    MyCos:= Precise(Cos(g),10);
  1268.    end;
  1269. {- MyTan ------------------------------------------------------------------------}
  1270. function MyTan(g:extended):extended;
  1271. begin
  1272.    if CalcMode=deg then g:=DegToRad(g);
  1273.    if Precise(Cos(g),10)=0 then begin
  1274.       MyTan:=0;
  1275.       RaisedError:='division by zero at Tan()';
  1276.       CalcError:=true;
  1277.       ErrorPosition:=0;
  1278.       exit;
  1279.       MyTan:=0;
  1280.       exit;
  1281.       end;
  1282.    MyTan:=Precise(Tan(g),10);{Precise(Sin(g),10)/Precise(Cos(g),10);}
  1283.    end;
  1284. {- MyArcSin ---------------------------------------------------------------------}
  1285. function MyArcSin(g:extended):extended;
  1286. begin
  1287.    if (1-sqr(g))<0 then begin
  1288.       RaisedError:='sqrt of negative value at ArcSin()';
  1289.       CalcError:=true;
  1290.       ErrorPosition:=0;
  1291.       MyArcSin:=0;
  1292.       exit;
  1293.       end;
  1294.    if sqrt(1-sqr(g))=0 then begin
  1295.       RaisedError:='division by zero at ArcSin()';
  1296.       CalcError:=true;
  1297.       ErrorPosition:=0;
  1298.       MyArcSin:=0;
  1299.       exit;
  1300.       end;
  1301.       {Evaluation:= ArcSin(g);{Precise(ArcTan (g/sqrt(1-sqr (g))),10);}
  1302.    if CalcMode=deg then MyArcSin:=RadToDeg(ArcSin(g)) else
  1303.       MyArcSin:=ArcSin(g);
  1304.    end;
  1305. {- MyArcCos --------------------------------------------------------------------}
  1306. function MyArcCos(g:extended):extended;
  1307. begin
  1308.    if g=0 then begin
  1309.       RaisedError:='division by zero at ArcCos()';
  1310.       CalcError:=true;
  1311.       ErrorPosition:=0;
  1312.       MyArcCos:=0;
  1313.       exit;
  1314.       end;
  1315.    if (1-sqr(g))<0 then begin
  1316.       RaisedError:='sqrt of negative value at ArcCos()';
  1317.       CalcError:=true;
  1318.       ErrorPosition:=0;
  1319.       MyArcCos:=0;
  1320.       exit;
  1321.       end;
  1322.    {Evaluation:= ArcCos(g);{Precise(ArcTan (sqrt (1-sqr (g)) /g),10);}
  1323.    if CalcMode=deg then MyArcCos:=RadToDeg(ArcCos(g)) else
  1324.       MyArcCos:=ArcCos(g);
  1325.    end;
  1326. {- MyArcCosH--------------------------------------------------------------------}
  1327. function MyArcCosh(g:extended):extended;
  1328. begin
  1329.    if g<1 then begin
  1330.       RaisedError:='sqrt of negative value at ArcCosh()';
  1331.       CalcError:=true;
  1332.       ErrorPosition:=0;
  1333.       MyArcCosh:=0;
  1334.       exit;
  1335.       end;
  1336.       MyArcCosh:=ArcCosh(g);
  1337.    end;
  1338. {- MyArcTanh -------------------------------------------------------------------}
  1339. function MyArcTanh(g:extended):extended;
  1340. begin
  1341.    if Abs(g)>1 then begin
  1342.       RaisedError:='out of domain at ArcTanh()';
  1343.       CalcError:=true;
  1344.       ErrorPosition:=0;
  1345.       MyArcTanh:=0;
  1346.       exit;
  1347.       end;
  1348.       MyArcTanh:=ArcTanh(g);
  1349.    end;
  1350. {- MyArcTan --------------------------------------------------------------------}
  1351. function MyArcTan(g:extended):extended;
  1352. begin
  1353.       if CalcMode=deg then MyArcTan:=RadToDeg(ArcTan(g)) else
  1354.       MyArcTan:=ArcTan(g)
  1355.    end;
  1356. {- MyCot ------------------------------------------------------------------------}
  1357. function MyCot(g:extended):extended;
  1358. begin
  1359.    if CalcMode=deg then g:=DegToRad(g);
  1360.    if Precise(g,10)=0 then begin
  1361.       RaisedError:='division by zero at Cot()';
  1362.       CalcError:=true;
  1363.       ErrorPosition:=0;
  1364.       MyCot:=0;
  1365.       exit;
  1366.       end;
  1367.    MyCot:= Cotan(g);
  1368.    {Precise(Cos(g),10)/Precise(Sin(g),10);}
  1369.    end;
  1370. {- MyCsch------------------------------------------------------------------------}
  1371. function MyCsch(g:extended):extended;
  1372. begin
  1373.    if Precise(Sinh(g),10)=0 then begin
  1374.       RaisedError:='division by zero at Csch()';
  1375.       CalcError:=true;
  1376.       ErrorPosition:=0;
  1377.       MyCsch:=0;
  1378.       exit;
  1379.       end;
  1380.    MyCsch:=1/Sinh(g);
  1381.    end;
  1382. {- MySech -----------------------------------------------------------------------}
  1383. function MySech(g:extended):extended;
  1384. begin
  1385.    if Precise(Cosh(g),10)=0 then begin
  1386.       RaisedError:='division by zero at Sech()';
  1387.       CalcError:=true;
  1388.       ErrorPosition:=0;
  1389.       MySech:=0;
  1390.       exit;
  1391.       end;
  1392.    MySech:=1/Cosh(g);
  1393.    end;
  1394. {- MyCsc ------------------------------------------------------------------------}
  1395. function MyCsc(g:extended):extended;
  1396. begin
  1397.    if CalcMode=deg then g:=DegToRad(g);
  1398.    if Precise(Sin(g),10)=0 then begin
  1399.       RaisedError:='division by zero at Csc()';
  1400.       CalcError:=true;
  1401.       ErrorPosition:=0;
  1402.       MyCsc:=0;
  1403.       exit;
  1404.       end;
  1405.    MyCsc:= 1/Precise(sin(g),10);
  1406.    end;
  1407. {- MyLn -------------------------------------------------------------------------}
  1408. function MyLn(g:extended):extended;
  1409. begin
  1410.    if g<=0 then begin
  1411.       RaisedError:='invalid natural log requested';
  1412.       CalcError:=true;
  1413.       ErrorPosition:=0;
  1414.       MyLn:=0;
  1415.       exit;
  1416.       end;
  1417.    MyLn:= ln(g);
  1418.    end;
  1419. {- MyLog ------------------------------------------------------------------------}
  1420. function MyLog(g:extended):extended;
  1421. begin
  1422.    if g<=0 then begin
  1423.       RaisedError:='invalid logarithm requested';
  1424.       CalcError:=true;
  1425.       ErrorPosition:=0;
  1426.       MyLog:=0;
  1427.       exit;
  1428.       end;
  1429.    {Evaluation:= ln(g)/ln(10);}
  1430.    MyLog:=log10(g);
  1431.    end;
  1432. {- ArcSec -----------------------------------------------------------------------}
  1433. function ArcSec(g:extended):extended;
  1434. begin
  1435.    if g=0 then begin
  1436.       RaisedError:='division by zero at ArcSec()';
  1437.       CalcError:=true;
  1438.       ErrorPosition:=0;
  1439.       ArcSec:=0;
  1440.       exit;
  1441.       end;
  1442.    if abs(1/g)>1 then begin
  1443.       RaisedError:='value out of domain at ArcSec()';
  1444.       CalcError:=true;
  1445.       ErrorPosition:=0;
  1446.       ArcSec:=0;
  1447.       exit;
  1448.       end;
  1449.   if CalcMode=deg then ArcSec:=RadToDeg(ArcCos(1/g)) else
  1450.      ArcSec:=ArcCos(1/g);
  1451.   end;
  1452. {- ArcCsc -----------------------------------------------------------------------}
  1453. function ArcCsc(g:extended):extended;
  1454. begin
  1455.    if g=0 then begin
  1456.       RaisedError:='division by zero at ArcCsc()';
  1457.       CalcError:=true;
  1458.       ErrorPosition:=0;
  1459.       ArcCsc:=0;
  1460.       exit;
  1461.       end;
  1462.    if abs(1/g)>1 then begin
  1463.       RaisedError:='value out of domain at ArcCsc()';
  1464.       CalcError:=true;
  1465.       ErrorPosition:=0;
  1466.       ArcCsc:=0;
  1467.       exit;
  1468.       end;
  1469.   if CalcMode=deg then ArcCsc:=RadToDeg(ArcSin(1/g)) else
  1470.      ArcCsc:=ArcSin(1/g);
  1471.    end;
  1472. {- ArcCot -----------------------------------------------------------------------}
  1473. function ArcCot(g:extended):extended;
  1474. begin
  1475.    if g=0 then begin
  1476.       RaisedError:='division by zero at ArcCot()';
  1477.       CalcError:=true;
  1478.       ErrorPosition:=0;
  1479.       ArcCot:=0;
  1480.       exit;
  1481.       end;
  1482.    if CalcMode=deg then ArcCot:=RadToDeg(ArcTan(1/g)) else
  1483.       ArcCot:=ArcTan(1/g);
  1484.   end;
  1485. {- ArcSech -----------------------------------------------------------------------}
  1486. function ArcSech(g:extended):extended;
  1487. begin
  1488.    if g=0 then begin
  1489.       RaisedError:='division by zero at ArcSech()';
  1490.       CalcError:=true;
  1491.       ErrorPosition:=0;
  1492.       ArcSech:=0;
  1493.       exit;
  1494.       end;
  1495.    if (1/g)<1 then begin
  1496.       RaisedError:='value out of domain at ArcSech()';
  1497.       CalcError:=true;
  1498.       ErrorPosition:=0;
  1499.       ArcSech:=0;
  1500.       exit;
  1501.       end;
  1502.    ArcSech:=ArcCosh(1/g);
  1503.    end;
  1504. {- ArcCsch -----------------------------------------------------------------------}
  1505. function ArcCsch(g:extended):extended;
  1506. begin
  1507.    if g=0 then begin
  1508.       RaisedError:='division by zero at ArcCsch()';
  1509.       CalcError:=true;
  1510.       ErrorPosition:=0;
  1511.       ArcCsch:=0;
  1512.       exit;
  1513.       end;
  1514.    ArcCsch:=ArcSinh(1/g);
  1515.    end;
  1516. {- ArcCoth -----------------------------------------------------------------------}
  1517. function ArcCoth(g:extended):extended;
  1518. begin
  1519.    if g=0 then begin
  1520.       RaisedError:='division by zero at ArcCoth()';
  1521.       CalcError:=true;
  1522.       ErrorPosition:=0;
  1523.       ArcCoth:=0;
  1524.       exit;
  1525.       end;
  1526.    if Abs(1/g)>1 then begin
  1527.       RaisedError:='value out of domain at ArcCoth()';
  1528.       CalcError:=true;
  1529.       ErrorPosition:=0;
  1530.       ArcCoth:=0;
  1531.       exit;
  1532.       end;
  1533.       ArcCoth:=ArcTanh(1/g);
  1534.    end;
  1535. {- MyNot -----------------------------------------------------------------}
  1536. function MyNot(g:extended):extended;
  1537. begin
  1538.    if trunc(g)<>g then begin
  1539.       RaisedError:='logic functions require integers';
  1540.       CalcError:=true;
  1541.       ErrorPosition:=0;
  1542.       MyNot:=0;
  1543.       exit;
  1544.       end;
  1545.    MyNot:=Not(trunc(g));
  1546.    end;
  1547. {- MyShl -----------------------------------------------------------------}
  1548. function MyShr(g,d:extended):extended;forward;
  1549. function MyShl(g,d:extended):extended;
  1550. begin
  1551.    if d<0 then MyShl:=MyShr(g,-d) else
  1552.    if (trunc(g)<>g) or (trunc(d)<>d) then begin
  1553.       RaisedError:='logic functions require integers';
  1554.       CalcError:=true;
  1555.       ErrorPosition:=0;
  1556.       MyShl:=0;
  1557.       exit;
  1558.       end else
  1559.    MyShl:=trunc(g) shl trunc(d)
  1560.    end;
  1561. {- MyShr -----------------------------------------------------------------}
  1562. function MyShr(g,d:extended):extended;
  1563. begin
  1564.    if d<0 then MyShr:=MyShl(g,-d) else
  1565.    if (trunc(g)<>g) or (trunc(d)<>d) then begin
  1566.       RaisedError:='logic functions require integers';
  1567.       CalcError:=true;
  1568.       ErrorPosition:=0;
  1569.       MyShr:=0;
  1570.       exit;
  1571.       end else
  1572.    MyShr:=trunc(g)shr trunc(d)
  1573.    end;
  1574. {- Euler's Indice, the Phi function --------------------------------------}
  1575. (*
  1576. function eInd(g:extended):extended;
  1577. var
  1578.    UsedPrimes:PPrimesArray;
  1579.    UniquePrimesCount: longint;
  1580.    {-----------------}
  1581.    procedure UniquePrimesAdd(PrimeToAdd: LongInt);
  1582.    var
  1583.       i:LongInt;
  1584.    begin
  1585.         for i:=0 to UniquePrimesCount-1 do begin
  1586.             if UsedPrimes^[i]=PrimeToAdd then exit;
  1587.             end;
  1588.             Calculator.PrimesAdd(PrimeToAdd,UsedPrimes,UniquePrimesCount);
  1589.       end;
  1590.    procedure Factoring(lin:longint);
  1591.    var
  1592.       lcnt:longint;
  1593.       CurrentCounter:longint;
  1594.    begin
  1595.       if (Calculator.AllPrimes^[Calculator.PrimesCount-1]<lin) then MyPrime(lin);
  1596.       CurrentCounter:=2;
  1597.       lcnt:=Calculator.AllPrimes^[CurrentCounter];
  1598.       if MyPrime(lin)=lin then begin
  1599.          UniquePrimesAdd(lin);
  1600.          end else
  1601.          while(lcnt*lcnt<=lin) do begin
  1602.             if (lin mod lcnt) = 0 then begin
  1603.                if MyPrime(lcnt)<>lcnt then
  1604.                   factoring(lcnt) else UniquePrimesAdd(lcnt);
  1605.                if MyPrime(lin div lcnt)<>(lin div lcnt) then
  1606.                   factoring(lin div lcnt) else UniquePrimesAdd(lin div lcnt);
  1607.                exit;
  1608.                end;
  1609.           inc(CurrentCounter);
  1610.           lcnt:=Calculator.AllPrimes^[CurrentCounter];
  1611.          end;
  1612.       end;
  1613.    {-----------------}
  1614.    var
  1615.       FinalResult:extended;
  1616.       i: longint;
  1617.    begin
  1618.      UniquePrimesCount:=0;
  1619.      if trunc(g)<>g then begin
  1620.         RaisedError:='Euler''s indice requires integers';
  1621.         CalcError:=true;
  1622.         ErrorPosition:=0;
  1623.         eInd:=0;
  1624.         exit;
  1625.         end;
  1626.      if g=0 then begin
  1627.         eInd:=0;
  1628.         exit;
  1629.         end;
  1630.      g:=Abs(g);
  1631.      FinalResult:=g;
  1632.      UsedPrimes:=nil;
  1633.      Factoring(Round(g));
  1634.      for i:=0 to UniquePrimesCount-1 do begin
  1635.         FinalResult:=FinalResult*(1-1/UsedPrimes^[i]);
  1636.         end;
  1637.      eInd:=FinalResult;
  1638.      Calculator.PrimesRemove(UsedPrimes);
  1639.    end;
  1640. *)
  1641. function MyAverage(g: extended):extended;
  1642. var
  1643.    ChildValue: extended;
  1644.    CurrentAverage: extended;
  1645.    i:integer;
  1646. begin
  1647.    i:=1;
  1648.    CurrentAverage:=g;
  1649.    while (Expression^.Child(i)<>nil) do begin
  1650.          ChildValue:=Evaluation(Expression^.Child(i));
  1651.          CurrentAverage:=CurrentAverage+ChildValue;
  1652.          inc(i);
  1653.          end;
  1654.    MyAverage:=CurrentAverage/i;
  1655.    end;
  1656. {---------------}
  1657. function MyMin(g: extended):extended;
  1658. var
  1659.    ChildValue: extended;
  1660.    i:integer;
  1661. begin
  1662.    i:=1;
  1663.    while (Expression^.Child(i)<>nil) do begin
  1664.          ChildValue:=Evaluation(Expression^.Child(i));
  1665.          if ChildValue<g then g:=ChildValue;
  1666.          inc(i);
  1667.          end;
  1668.    MyMin:=g;
  1669.    end;
  1670. {-----------------------}
  1671. function MyMax(g: extended):extended;
  1672. var
  1673.    ChildValue: extended;
  1674.    i:integer;
  1675. begin
  1676.    i:=1;
  1677.    while (Expression^.Child(i)<>nil) do begin
  1678.          ChildValue:=Evaluation(Expression^.Child(i));
  1679.          if ChildValue>g then g:=ChildValue;
  1680.          inc(i);
  1681.          end;
  1682.    MyMax:=g;
  1683.    end;
  1684. {-------------------------}
  1685. (*
  1686. function MyPrimen(g: extended):extended;
  1687. var
  1688.    LocalCounter: longint;
  1689. begin
  1690.    if g<=0 then begin
  1691.       CalcError:=True;
  1692.       ErrorPosition:=0;
  1693.       RaisedError:='invalid PrimeN request';
  1694.       MyPrimeN:=0;
  1695.       exit;
  1696.       end;
  1697.    LocalCounter:=Calculator.AllPrimes[Calculator.PrimesCount-1];
  1698.    g:=g+1;
  1699.    while(Calculator.PrimesCount<=g) do begin
  1700.      MyPrime(LocalCounter);
  1701.      LocalCounter:=LocalCounter+2;
  1702.      end;
  1703.      MyPrimen:=Calculator.AllPrimes[trunc(g)];
  1704.    end;
  1705. {-------------------------}
  1706. function MyPrimeC(g: extended):extended;
  1707. var
  1708.    i: integer;
  1709. begin
  1710.    if g<0 then begin
  1711.       CalcError:=True;
  1712.       ErrorPosition:=0;
  1713.       RaisedError:='invalid PrimeC request';
  1714.       MyPrimeC:=0;
  1715.       exit;
  1716.       end;
  1717.    if (g>Calculator.CurrentPrime) then MyPrime(g);
  1718.    for i:=Calculator.PrimesCount-1 downto 0 do begin
  1719.    if  g>=Calculator.AllPrimes^[i] then begin
  1720.           MyPrimeC:=i-1;
  1721.           exit;
  1722.           end;
  1723.       end;
  1724.       CalcError:=True;
  1725.       ErrorPosition:=0;
  1726.       RaisedError:='unexpected PrimeC return value';
  1727.       MyPrimeC:=0;
  1728.       end;
  1729. {-----------------------}
  1730. *)
  1731. function Binom(n,j:extended):extended;
  1732. var
  1733.    _1Fact,_2Fact,_3Fact:extended;
  1734. begin
  1735.    _1Fact:=Factor(n,0.01);
  1736.    _2Fact:=Factor(j,0.01);
  1737.    _3Fact:=Factor(n-j,0.01);
  1738.    if (_2Fact=0) or (_3Fact=0) then begin
  1739.       CalcError:=True;
  1740.       ErrorPosition:=0;
  1741.       RaisedError:='factor in binom results to infinity';
  1742.       binom:=0;
  1743.       exit;
  1744.       end;
  1745.    Binom:=_1Fact/(_2Fact*_3Fact);
  1746.    end;
  1747. {----------------------}
  1748. var
  1749.    g, d : extended;
  1750. begin
  1751.   try
  1752.    Evaluation:=0;
  1753.    if CalcError=true then exit;
  1754.    if Expression^.Contents='=' then Evaluation:=Evaluation(Expression^.Child(0)) else
  1755.    if Expression^.NodeType = NodeValue then Evaluation := Expression^.NodeContents^.MyValue else
  1756.    if Expression^.NodeType = NodeVariable then Evaluation := VariableValue(Expression^.NodeContents^.MyVariable) else
  1757.    if Expression^.NodeType = NodeSingle then begin
  1758.        g := Evaluation(Expression^.Child(0));
  1759.        if Expression.NodeContents.MySingle[1]='-' then begin
  1760.        Delete(Expression.NodeContents.MySingle,1,1);
  1761.        NextInteger:=-1
  1762.        end else NextInteger:=1;
  1763.        if CompareText(Expression^.NodeContents^.MySingle,'binom')=0 then Evaluation:=NextInteger*Binom(g,Evaluation(Expression^.Child(1))) else
  1764.        if CompareText(Expression^.NodeContents^.MySingle,'perfect')=0 then Evaluation:=NextInteger*Perfect(g) else
  1765.        if CompareText(Expression^.NodeContents^.MySingle,'mersgen')=0 then Evaluation:=NextInteger*PMersienne(g) else
  1766.        if CompareText(Expression^.NodeContents^.MySingle,'genmers')=0 then Evaluation:=NextInteger*MersienneP(g) else
  1767.        if CompareText(Expression^.NodeContents^.MySingle,'mersienne')=0 then Evaluation:=NextInteger*MersienneN(g) else
  1768.        if CompareText(Expression^.NodeContents^.MySingle,'mersiennegen')=0 then Evaluation:=NextInteger*MersienneG(g) else
  1769. (*       if CompareText(Expression^.NodeContents^.MySingle,'primec')=0 then Evaluation:=NextInteger*MyPrimec(g) else
  1770.        if CompareText(Expression^.NodeContents^.MySingle,'prime')=0 then Evaluation:=NextInteger*MyPrime(g) else
  1771.        if CompareText(Expression^.NodeContents^.MySingle,'primen')=0 then Evaluation:=NextInteger*MyPrimen(g) else*)
  1772. {sin}  if CompareText(Expression^.NodeContents^.MySingle,'sin')=0 then Evaluation:=NextInteger*MySin(g) else
  1773.        if CompareText(Expression^.NodeContents^.MySingle,'arcsin')=0 then Evaluation:=NextInteger*MyArcSin(g) else
  1774.        if CompareText(Expression^.NodeContents^.MySingle,'sinh')=0 then Evaluation:=NextInteger*Sinh(g) else {(exp(g)-exp(-g))/2}
  1775.        if CompareText(Expression^.NodeContents^.MySingle,'arcsinh')=0 then Evaluation:=NextInteger*ArcSinh(g) else
  1776. {cos}  if CompareText(Expression^.NodeContents^.MySingle,'cos')=0 then Evaluation:=NextInteger*MyCos(g) else
  1777.        if CompareText(Expression^.NodeContents^.MySingle,'arccos')=0 then Evaluation:=NextInteger*MyArcCos(g) else
  1778.        if CompareText(Expression^.NodeContents^.MySingle,'cosh')=0 then Evaluation:= NextInteger*cosh(g){(exp(g)+exp(-g))/2} else
  1779.        if CompareText(Expression^.NodeContents^.MySingle,'arccosh')=0 then Evaluation:=NextInteger*MyArcCosh(g) else
  1780. {tan}  if CompareText(Expression^.NodeContents^.MySingle,'tan')=0 then Evaluation:=NextInteger*MyTan(g) else
  1781.        if CompareText(Expression^.NodeContents^.MySingle,'arctan')=0 then Evaluation:=NextInteger*MyArcTan(g) else
  1782.        if CompareText(Expression^.NodeContents^.MySingle,'tanh')=0 then Evaluation:=NextInteger*tanh(g) else {Evaluation:=(exp(g)-exp(-g))/(exp(g)+exp(-g)); {tanh has R for domain}
  1783.        if CompareText(Expression^.NodeContents^.MySingle,'arctanh')=0 then Evaluation:=NextInteger*MyArcTanh(g) else
  1784. {cot}  if CompareText(Expression^.NodeContents^.MySingle,'cot')=0 then Evaluation:=NextInteger*MyCot(g) else
  1785.        if CompareText(Expression^.NodeContents^.MySingle,'coth')=0 then Evaluation:=NextInteger*coth(g) else
  1786.        if (CompareText(Expression^.NodeContents^.MySingle,'arccot')=0) then Evaluation:=NextInteger*arccot(g) else
  1787.        if (CompareText(Expression^.NodeContents^.MySingle,'arccoth')=0) then Evaluation:=NextInteger*arccoth(g) else
  1788. {sec}  if CompareText(Expression^.NodeContents^.MySingle,'sec')=0 then Evaluation:=NextInteger*Sec(g) else
  1789.        if (CompareText(Expression^.NodeContents^.MySingle,'arcsec')=0) then Evaluation:=NextInteger*arcsec(g) else
  1790.        if CompareText(Expression^.NodeContents^.MySingle,'sech')=0 then Evaluation:=NextInteger*MySech(g) else
  1791.        if (CompareText(Expression^.NodeContents^.MySingle,'arcsech')=0) then Evaluation:=NextInteger*arcsech(g) else
  1792. {csc}  if CompareText(Expression^.NodeContents^.MySingle,'csc')=0 then Evaluation:=NextInteger*MyCsc(g) else
  1793.        if (CompareText(Expression^.NodeContents^.MySingle,'arccsc')=0) then Evaluation:=NextInteger*arccsc(g) else
  1794.        if CompareText(Expression^.NodeContents^.MySingle,'csch')=0 then Evaluation:=NextInteger*MyCsch(g) else
  1795.        if (CompareText(Expression^.NodeContents^.MySingle,'arccsch')=0) then Evaluation:=NextInteger*arccsch(g) else
  1796. {etc}  if CompareText(Expression^.NodeContents^.MySingle,'new')=0 then Evaluation:=NextInteger*g else
  1797.        if CompareText(Expression^.NodeContents^.MySingle,'random')=0 then Evaluation:=NextInteger*MyRandom(g) else
  1798.        if CompareText(Expression^.NodeContents^.MySingle,'sqr')=0 then Evaluation:= NextInteger*sqr(g) else
  1799.        if CompareText(Expression^.NodeContents^.MySingle,'sqrt')=0 then Evaluation:= NextInteger*MySqrt(g) else
  1800.        if CompareText(Expression^.NodeContents^.MySingle,'floor')=0 then Evaluation:=NextInteger*floor(g) else
  1801.        if CompareText(Expression^.NodeContents^.MySingle,'ceil')=0 then Evaluation:=NextInteger*ceil(g) else
  1802.        if CompareText(Expression^.NodeContents^.MySingle,'ln')=0 then Evaluation:=NextInteger*MyLn(g) else
  1803.        if CompareText(Expression^.NodeContents^.MySingle,'exp')=0 then Evaluation:= NextInteger*exp(g) else
  1804.        if CompareText(Expression^.NodeContents^.MySingle,'logn')=0 then Evaluation:=NextInteger*logn(g,Evaluation(Expression^.Child(1))) else
  1805.        if CompareText(Expression^.NodeContents^.MySingle,'log')=0 then Evaluation:=NextInteger*MyLog(g) else
  1806.        if CompareText(Expression^.NodeContents^.MySingle,'trunc')=0 then Evaluation:= NextInteger*trunc(g) else
  1807.        if CompareText(Expression^.NodeContents^.MySingle,'round')=0 then Evaluation:= NextInteger*round(g) else
  1808.        if CompareText(Expression^.NodeContents^.MySingle,'int')=0 then Evaluation:= NextInteger*int(g) else
  1809.        if CompareText(Expression^.NodeContents^.MySingle,'abs')=0 then Evaluation:= NextInteger*abs(g) else
  1810.        if CompareText(Expression^.NodeContents^.MySingle,'frac')=0 then Evaluation:= NextInteger*(g-trunc(g)) else
  1811.        if CompareText(Expression^.NodeContents^.MySingle,'not')=0 then Evaluation:=NextInteger*MyNot(g) else
  1812.        (*if CompareText(Expression^.NodeContents^.MySingle,'eind')=0 then Evaluation:=NextInteger*eInd(g) else*)
  1813.        (*if CompareText(Expression^.NodeContents^.MySingle,'phi')=0 then Evaluation:=NextInteger*eInd(g) else*)
  1814.        if CompareText(Expression^.NodeContents^.MySingle,'max')=0 then Evaluation:=NextInteger*MyMax(g) else
  1815.        if CompareText(Expression^.NodeContents^.MySingle,'min')=0 then Evaluation:=NextInteger*MyMin(g) else
  1816.        if CompareText(Expression^.NodeContents^.MySingle,'average')=0 then Evaluation:=NextInteger*MyAverage(g) else
  1817.       if CompareText(Expression^.NodeContents^.MySingle,'shl')=0 then Evaluation:=MyShl(g,Evaluation(Expression^.Child(1))) else
  1818.       if CompareText(Expression^.NodeContents^.MySingle,'shr')=0 then Evaluation:=MyShr(g,Evaluation(Expression^.Child(1))) else
  1819.       if CompareText(Expression^.NodeContents^.MySingle,'beta')=0 then Evaluation:=NextInteger*beta(g,Evaluation(Expression^.Child(1)),Evaluation(Expression^.Child(2))) else
  1820.       if CompareText(Expression^.NodeContents^.MySingle,'gamma')=0 then Evaluation:=NextInteger*Gamma(g,Evaluation(Expression^.Child(1))) else
  1821.       if CompareText(Expression^.NodeContents^.MySingle,'fib')=0 then begin
  1822.          if (trunc(g)<>g) or (g<0) then begin
  1823.             RaisedError:='fibonacci requires positive integers';
  1824.             CalcError:=true;
  1825.             ErrorPosition:=0;
  1826.             exit;
  1827.             end;
  1828.             Evaluation:=NextInteger*Fib(g);
  1829.          end else
  1830.       if CompareText(Expression^.NodeContents^.MySingle,'lcm')=0 then Evaluation:=NextInteger*lcm(g) else
  1831.       if CompareText(Expression^.NodeContents^.MySingle,'ppcm')=0 then Evaluation:=NextInteger*lcm(g) else      
  1832.       if CompareText(Expression^.NodeContents^.MySingle,'pgcd')=0 then Evaluation:=NextInteger*gcd(g) else
  1833.       if CompareText(Expression^.NodeContents^.MySingle,'gcd')=0 then Evaluation:=NextInteger*gcd(g) else
  1834.        begin {else}
  1835.                 RaisedError:='unknown function "'+Expression^.NodeContents^.MySingle+'"';
  1836.                 CalcError:=true;
  1837.                 ErrorPosition:=0;
  1838.                 exit;
  1839.                 end;
  1840.    end{else}
  1841.    else begin
  1842.       g := Evaluation(Expression^.Child(0));
  1843.       if CalcError=true then exit;
  1844.       d := Evaluation(Expression^.Child(1));
  1845.       if CalcError=true then exit;
  1846.       if (CompareText(Expression^.NodeContents^.MyOperator,'xor')=0) then Result:=trunc(g) xor trunc(d) else
  1847.       if (CompareText(Expression^.NodeContents^.MyOperator,'xnor')=0) then Result:=not(trunc(g) xor trunc(d)) else
  1848.       if (CompareText(Expression^.NodeContents^.MyOperator,'or')=0) then Result:=trunc(g) or trunc(d) else
  1849.       if (CompareText(Expression^.NodeContents^.MyOperator,'nor')=0) then Result:=not(trunc(g) or trunc(d)) else
  1850.       if (CompareText(Expression^.NodeContents^.MyOperator,'and')=0) then Result:=trunc(g) and trunc(d) else
  1851.       if (CompareText(Expression^.NodeContents^.MyOperator,'nand')=0) then Result:=not (trunc(g) and trunc(d)) else
  1852.       case Expression^.NodeContents^.MyOperator[1] of
  1853.          '&'   : Result:=trunc(g) and trunc(d);
  1854.          'm'   : Result:=trunc(g) mod trunc(d);
  1855.          '%'   : Result := (d/100)*g;
  1856.          '+'   : Result := g + d;
  1857.          '-'   : Result := g - d;
  1858.          '*'   : Result := g * d;
  1859.          'ª'   : begin {detects zero divisions!!!}
  1860.                  if d=0 then begin
  1861.                    RaisedError:='division by zero at int div';
  1862.                    CalcError:=true;
  1863.                    ErrorPosition:=0;
  1864.                    exit;
  1865.                    end;
  1866.                  Result := trunc(g/d);
  1867.                  end;
  1868.          '/'   : begin
  1869.                  Result:=g/d;
  1870.                  end;
  1871.          '^'   : begin
  1872.                  Result := Power(g,d);
  1873.                  if CalcError=true then exit;
  1874.                  end;
  1875.          '!'   : begin
  1876.                  Result := Factor(g,0.01);
  1877.                  if CalcError=true then exit;
  1878.                  end;
  1879.          '\'   : begin
  1880.                  if d=0 then Result:=0 else
  1881.                  if d>0 then Result:=Power(d,1/g)
  1882.                   else
  1883.                    if (Trunc(g)=g) and (odd(Trunc(g))) then Result:=-Power(-d,1/g)
  1884.                    else begin
  1885.                     RaisedError:='invalid root of negative value';
  1886.                     CalcError:=true;
  1887.                     ErrorPosition:=0;
  1888.                     exit;
  1889.                     end;
  1890.                   end;
  1891.          end;{case}
  1892.      Evaluation:=Result;
  1893.    end;{else}
  1894.    exit;
  1895.    except
  1896.       on EAccessViolation do RaisedError:='multithread collision, please retry';
  1897.       on EDivByZero  do RaisedError:='division by zero';
  1898.       on EIntOverFlow  do RaisedError:='integer overflow';
  1899.       on EInvalidOp  do RaisedError:='undefined instruction';
  1900.       on EOutOfMemory do RaisedError:='out of memory';
  1901.       on EOverflow do RaisedError:='floating point overflow';
  1902.       on ERangeError do RaisedError:='range check error';
  1903.       on EStackOverflow do RaisedError:='stack overflow';
  1904.       on EZeroDivide do RaisedError:='division by zero';
  1905.       on EUnderFlow  do RaisedError:='floating point underflow';
  1906.       else RaisedError:='general exception fault';
  1907.       end;{evaluation}
  1908.       CalcError:=true;
  1909.       ErrorPosition:=0;
  1910.       Evaluation:=0;
  1911.       exit;
  1912.    end;
  1913. end.
  1914.